import { _decorator, Component, Node, AudioSource, toDegree, Vec2, instantiate, AudioClip, Vec3, ProgressBar, Label } from 'cc';
import { Battle } from '../Battle';
import { Utitls } from '../Common/Utils';
import { Globals } from '../Globals';
import { Player_Buttle } from '../Player/Player_Buttle';
import { AnimationController } from './AnimationController';
import { EnemyController } from './Enemy/EnemyController';
import { TreeController } from './TreeController';
const { ccclass, property } = _decorator;

export enum TeammateAnimType {
    Idle,
    Walk,
    Attack,
    Skill
}

export class TeammateAnimInfo {
    public hurt: number = 0;
    public animName: string = "";
    public isLoop: boolean = false;
    public animType: TeammateAnimType = TeammateAnimType.Idle;
    public befEffect: string = "";
    public aftEffect: string = "";
    public hitEffect: string = "";
    public attackTime: number = 4;
    public attackInterval: number = 0.1;
    public effectNum: number = 1;
    public attackRang: number = 640;
}

@ccclass('TeammateController')
export class TeammateController extends Component {

    @property(Node)
    public bodyNode: Node = null;
    @property(Node)
    private anim: Node = null;
    @property(Node)
    public gunNode: Node = null;
    @property(ProgressBar)
    public cdProgress: ProgressBar = null;
    @property(Label)
    public cdLabel: Label = null;

    public curAttackInterval: number = 1;
    public attackInterval: number = 1;
    public _audioSound: AudioSource;
    public _attackAudio: AudioClip = null;
    public _skillAudio: AudioClip = null;
    // 移动方向
    public _moveDirection: number = 0;
    //是否在攻击
    public _isAttack: boolean = false;
    // 攻击方向
    private _attackDirection: number = 0;

    public attackTarget: Node = null;

    public teammateAnimInfoData: Array<TeammateAnimInfo> = [];
    public curTeammateAnimInfo: TeammateAnimInfo;
    public anmController: AnimationController;
    public effectAttackNodes = [];

    private skillTimeInterval: number = 15;
    private skillTime: number = 0;
    private curSkillAttackTime: number = 0;

    onEnable(): void {
        this.anmController = this.anim.getComponent(AnimationController);
        this.anmController.completeListener = this.OnCompleteListener.bind(this);
        this._audioSound = this.node.getComponent(AudioSource);
        this._isAttack = false;
        this.OnChildInit();
        // this.PlayAnim(TeammateAnimType.Idle);
        this.scheduleOnce(function () {
            this.OnSkillAttack();
        }.bind(this), 0.5);
        this.cdLabel.node.active = false;
    }

    //技能攻击
    OnSkillAttack() {
        this.PlayAnim(TeammateAnimType.Skill, 1);
        // this.skillTimeInterval = this.skillTimeInterval + this.curTeammateAnimInfo.attackTime;
        let myThis = this;
        this.scheduleOnce(function () {
            myThis.StartCreatePlayerSkill();
            if (myThis._audioSound && myThis._skillAudio) {
                myThis._audioSound.playOneShot(myThis._skillAudio);
            }
        }.bind(this), 0.5);
    }

    OnChildInit() {

    }

    GetTeammateAnimInfoData(animType: TeammateAnimType) {
        for (let index = 0; index < this.teammateAnimInfoData.length; index++) {
            const element = this.teammateAnimInfoData[index];
            if (animType == element.animType) {
                return element;
            }
        }
        return null;
    }

    PlayAnim(animType: TeammateAnimType, track: number = 0) {
        if (this.anmController) {
            let animData = this.GetTeammateAnimInfoData(animType);
            if (animData) {
                this.curTeammateAnimInfo = animData;
                this.anmController.UpdateAnim(this.curTeammateAnimInfo.animName, this.curTeammateAnimInfo.isLoop, track);
            }
        }
    }

    update(deltaTime: number) {
        if (Battle.startGame) {
            this.CalculateAttackDirection();
            if (this._isAttack) {
                this.curAttackInterval -= deltaTime;
                this.OnAttack(this.curAttackInterval);
            }
            else {
                this.curAttackInterval = 0;
                this.PlayAnim(TeammateAnimType.Idle);
            }
            this.skillTime -= deltaTime;
            if (this.skillTime <= 0) {
                this.OnSkillAttack();
                this.skillTime = this.skillTimeInterval;
            }
            this.cdProgress.progress = this.skillTime / this.skillTimeInterval;
            this.cdLabel.string = this.skillTime.toString();
        }
    }

    OnCompleteListener(animName) {
        // this.curAttackInterval = 1;
        // this.PlayAnim(TeammateAnimType.Idle);
    }

    OnAttack(interval: number) {
        if (interval <= 0) {
            this.curAttackInterval = 1.5;
            // console.log("播放攻击动画");
            // if (this.normalAttackNum >= 3) {
            //     this.PlayAnim(TeammateAnimType.Skill);
            //     this.StartCreatePlayerSkill();
            //     this.normalAttackNum = 0;
            //     this._audioSound.playOneShot(this._skillAudio);
            // }
            // else 
            {
                this.PlayAnim(TeammateAnimType.Attack, 1);
                this.StartCreatePlayerBullet();
                this._audioSound.playOneShot(this._attackAudio);
            }
        }
    }

    CalculateAttackDirection() {
        this.attackTarget = this.getAttackTarget();
        if (this.attackTarget) {
            let pointNode = this.attackTarget.getChildByName("Point");
            if (pointNode == null) {
                pointNode = this.attackTarget;
            }
            const y = pointNode.getWorldPosition().y - this.node.getWorldPosition().y;
            const x = pointNode.getWorldPosition().x - this.node.getWorldPosition().x;
            this._attackDirection = Math.atan2(y, x);
            this._isAttack = true;
        }
        else {
            // this.anmController.SetNone();
            this.PlayAnim(TeammateAnimType.Idle);
            this._isAttack = false;
        }
    }

    /**
    * 创建player技能(技能攻击)
    *  */
    StartCreatePlayerSkill() {
        if (this.curTeammateAnimInfo == null) {
            return;
        }
        // const muzzle = this.gunNode.getChildByName("muzzle");
        // let pointNode = this.attackTarget.getChildByName("Point");
        // // if (pointNode == null) {
        // pointNode = this.attackTarget;
        // }
        // const playerBulletNode = Globals.getNode(this.curTeammateAnimInfo.befEffect, Battle.ContentParent);
        // playerBulletNode.setWorldPosition(pointNode.getWorldPosition());//设置子弹初始点
        // playerBulletNode.angle = angle; //设置子弹偏移角度，最近敌人的方向
        // 改变角色方向
        // if (pointNode.getWorldPosition().x >= this.node.getWorldPosition().x) {
        //     this.bodyNode.setScale(1, 1);
        // } else {
        //     this.bodyNode.setScale(-1, 1);
        // }
        let animInfo = this.GetTeammateAnimInfoData(TeammateAnimType.Skill);
        this.curSkillAttackTime = animInfo.attackTime;
        this.SkillAttack();
        let myThis = this;
        this.scheduleOnce(function () {
            myThis.ShowSkillHitEffect();
        }.bind(this), 0.5);
    }

    SkillAttack() {
        //创建技能特效
        let animInfo = this.GetTeammateAnimInfoData(TeammateAnimType.Skill);
        let createEffects = [];
        for (let index = 0; index < Battle.SkillEffectParent.children.length; index++) {
            const element = Battle.SkillEffectParent.children[index];
            let effectWorldPos = element.getWorldPosition();
            let distance = Vec2.distance(this.node.getWorldPosition(), effectWorldPos);
            if (distance <= animInfo.attackRang) {
                createEffects.push(element);
            }
        }
        for (let index = 0; index < animInfo.effectNum; index++) {
            const effectNode = Globals.getNode(animInfo.befEffect, Battle.ContentParent);
            let effectIndex = Utitls.Random(0, createEffects.length - 1);
            let effect = createEffects[effectIndex];
            const result = new Vec3();
            Vec3.add(result, this.node.position, effect.position);
            effectNode.setPosition(result);
            effectNode.active = true;
        }
        this.curSkillAttackTime -= animInfo.attackInterval;
        if (this.curSkillAttackTime <= 0) {

        }
        else {
            let myThis = this;
            this.scheduleOnce(function () {
                myThis.SkillAttack();
            }.bind(this), animInfo.attackInterval);
        }
    }

    ShowSkillHitEffect() {
        let animInfo = this.GetTeammateAnimInfoData(TeammateAnimType.Skill);
        let targets = this.getAttackTargetsByNode(this.node, animInfo.attackRang);
        for (let index = 0; index < targets.length; index++) {
            const element = targets[index];
            if (element) {
                let controller = element.getComponent(EnemyController);
                if (!controller.isDie) {
                    /*const hitEffect = Globals.getNode(animInfo.hitEffect, Battle.ContentParent);
                    if (hitEffect) {
                        hitEffect.setWorldPosition(element.getWorldPosition());
                        hitEffect.active = true;
                    }*/
                    controller.Injured(animInfo.hurt);
                }
            }
        }
    }

    /**
    * 创建player玩家子弹(普通攻击)
    *  */
    StartCreatePlayerBullet() {
        // console.log("创建子弹");
        if (this.curTeammateAnimInfo == null) {
            return;
        }
        // const muzzle = this.gunNode.getChildByName("muzzle");
        let angle = toDegree(this._attackDirection);
        const playerBulletNode = Globals.getNode(this.curTeammateAnimInfo.befEffect, Battle.ContentParent);
        if (playerBulletNode) {
            playerBulletNode.getComponent(Player_Buttle).hurt = this.curTeammateAnimInfo.hurt;
            playerBulletNode.setWorldPosition(this.gunNode.getWorldPosition());//设置子弹初始点
            playerBulletNode.angle = angle; //设置子弹偏移角度，最近敌人的方向
            // 修改子弹节点Player_Buttle组件中的值
            playerBulletNode.getComponent(Player_Buttle).moveDirection = this._attackDirection;
            playerBulletNode.getComponent(Player_Buttle).isMoveing = true;
            playerBulletNode.active = true;
        }

        // 改变角色方向
        if (this.attackTarget.getWorldPosition().x >= this.node.getWorldPosition().x) {
            this.bodyNode.setScale(1, 1);
        } else {
            this.bodyNode.setScale(-1, 1);
        }
    }

    /**
    * 攻击最近的敌人（获取最近敌人的方向）
    */
    getAttackTarget() {
        const Enemys = Battle.EnemyParent.children;
        const worldPos = this.node.getWorldPosition();
        let target: Node = null;
        let minDistance = 1000;
        let range = 400;
        for (let i = 0; i < Enemys.length; i++) {
            let enemyNode = Enemys[i];
            let result = false;
            let nodeName = enemyNode.name;
            if (nodeName.includes("Enemy") || nodeName.includes("Boss")) {
                let enemyCom = enemyNode.getComponent(EnemyController);
                if (!enemyCom.isDie) {
                    result = true;
                }
            }
            else if (nodeName.includes("Tree")) {
                let enemyCom = enemyNode.getComponent(TreeController);
                if (!enemyCom.isDie) {
                    result = true;
                }
            }
            if (result) {
                const distance = Vec2.distance(enemyNode.getWorldPosition(), worldPos);
                if (distance <= minDistance && distance <= range) {
                    target = enemyNode;
                }
            }
        }
        return target;
    }


    /**
    * 获得多个攻击对象
    */
    getAttackTargetsByNode(target, range) {
        const Enemys = Battle.EnemyParent.children;
        const worldPos = target.getWorldPosition();
        let targets = [];
        let minDistance = 1000;
        for (let i = 0; i < Enemys.length; i++) {
            let enemyNode = Enemys[i];
            let result = false;
            let nodeName = enemyNode.name;
            if (nodeName.includes("Enemy") || nodeName.includes("Boss")) {
                let enemyCom = enemyNode.getComponent(EnemyController);
                if (!enemyCom.isDie) {
                    result = true;
                }
            }
            if (result) {
                const distance = Vec2.distance(enemyNode.getWorldPosition(), worldPos);
                if (distance <= minDistance && distance <= range) {
                    targets.push(enemyNode);
                }
            }
        }
        return targets;
    }

    CreatorRouItem(enemyNode: Node, prefab) {
        let obj = instantiate(prefab);
        Battle.ContentParent.addChild(obj);
        let pos = enemyNode.position;
        obj.setPosition(pos);
        obj.active = true;
    }

}


